<template>
    <div class="lowCodeContainer">
        <div class="leftContainer">
            <CommonIndex />
            <FormIndex />
            <LayOutIndex />
            <FeedBackIndex />
            <ExtensionIndex />
            <FileInfoIndex />
            <CarouselIndex />
            <CardIndex />
            <NavigationIndex />
            <SpecialComponentIndex />
            <EchartsIndex />
        </div>

        <div class="rightContainer">
            <div class="topContainer">
                <el-button type="primary" @click="route.query.id ? dialogSaveOrUpdateVisible = true : dialogVisible = true">保存</el-button>
                <el-button type="danger" @click="clearAll()">清空</el-button>
                <el-button @click="globalComponentDrawer()">全局配置</el-button>
            </div>
            <div class="draggableContainer" @dblclick="globalComponentDrawer()">
                <draggable
                    :list="list"
                    animation="300"
                    :force-fallback="true"
                    :group="{name:'lowcode'}"
                    class="draggableClass"
                    item-key="id"
                >
                    <template #item="{ element }">
                        <div class="itemClass">
                            <component :is="element.component" :propJson="element.propJson" v-if="itemFlag" :commonParam="globalComponentJson.commonParam" @click.stop=""  @dblclick.stop="changeComponentInfo(element)"/>
                            <component is="CloseCircleOutlined" class="closeClass" @click.stop="" @dblclick.stop="deleteComponent(element)"/>
                        </div>
                    </template>
                </draggable>
            </div>
        </div>

        <div>
            <el-drawer
                v-model="isShowDrawer"
                :title="currentDrawerTitle"
                :before-close="handleClose"
                :lock-scroll="true"
                :close-on-click-modal="false"
            >
                <div>
                    <component :is="currentDrawer" :commonParam="globalComponentJson.commonParam"/>
                </div>
                <template #footer>
                    <div style="flex: auto">
                        <el-button @click="cancelClick">取消</el-button>
                        <el-button type="primary" @click="confirmClick">确认</el-button>
                    </div>
                </template>
            </el-drawer>
        </div>

        <div>
            <el-drawer
                v-model="isShowGlobalDrawer"
                title="全局配置"
                :before-close="handleGlobalClose"
                :lock-scroll="true"
                :close-on-click-modal="false"
            >
                <div>
                    <GlobalComponentDrawer :commonParam="globalComponentJson.commonParam"/>
                </div>
                <template #footer>
                    <div style="flex: auto">
                        <el-button @click="cancelGlobalClick">取消</el-button>
                        <el-button type="primary" @click="confirmGlobalClick">确认</el-button>
                    </div>
                </template>
            </el-drawer>
        </div>

        <div>
            <el-dialog
                v-model="dialogVisible"
                title="保存组件"
                width="500"
            >
                <el-form :model="componentRequestInfo" :rules="containerRules" label-width="auto" style="max-width: 600px" ref="containerFormRef">
                    <el-form-item label="组件名称-英文" prop="componentName">
                        <el-input v-model="componentRequestInfo.componentName"/>
                    </el-form-item>
                    <el-form-item label="组件名称-中文" prop="componentCnName">
                        <el-input v-model="componentRequestInfo.componentCnName"/>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <div class="dialog-footer">
                        <el-button @click="dialogVisible = false">取消</el-button>
                        <el-button type="primary" :loading="saveLoading" @click="saveComponent(containerFormRef)">
                            确认
                        </el-button>
                    </div>
                </template>
            </el-dialog>
        </div>

        <div>
            <el-dialog
                v-model="dialogSaveOrUpdateVisible"
                title="保存OR修改"
                width="500"
            >
                <template #footer>
                    <div class="dialog-footer">
                        <el-button @click="dialogSaveOrUpdateVisible = false">取消</el-button>
                        <el-button type="danger" :loading="updateSaveLoading" @click="updateComponentBefore()">
                            保存为原始组件
                        </el-button>
                        <el-button type="primary" @click="saveComponentBefore()">
                            新增组件
                        </el-button>
                    </div>
                </template>
            </el-dialog>
        </div>
    </div>
</template>

<script name="LowCodeBuilder" lang="ts" setup>
import {createTag, deepCopy} from "@/utils/ywuCommon";
import CarouselIndex from "@/components/lowcode/carousel/CarouselIndex.vue";
import CardIndex from "@/components/lowcode/card/CardIndex.vue";
import CommonIndex from "@/components/lowcode/common/CommonIndex.vue";
import LayOutIndex from "@/components/lowcode/layout/LayOutIndex.vue";
import FormIndex from "@/components/lowcode/form/FormIndex.vue";
import FeedBackIndex from "@/components/lowcode/feedBack/FeedBackIndex.vue";
import NavigationIndex from "@/components/lowcode/navigation/NavigationIndex.vue";
import SpecialComponentIndex from "@/components/lowcode/special/SpecialComponentIndex.vue";
import GlobalComponentDrawer from "@/components/lowcode/common/drawer/GlobalComponentDrawer.vue";
import ExtensionIndex from "@/components/lowcode/extension/ExtensionIndex.vue";
import FileInfoIndex from "@/components/lowcode/file/FileInfoIndex.vue";
import EchartsIndex from "@/components/lowcode/echarts/EchartsIndex.vue";
import {ElMessageBox, ElNotification, FormInstance} from 'element-plus'
import {componentInfoCreate, componentInfoQuery, componentInfoUpdate} from "@/request/components";
import jsonpath from "jsonpath";
import {computed, nextTick, ref} from "vue";
import {useLowCodeStore} from "@/stores/lowcode/lowcode";
import {useRoute, useRouter} from "vue-router";

let isShowDrawer = computed(() => {return useLowCodeStore().isShowDrawer});
let currentDrawer = computed(() => {return useLowCodeStore().currentDrawer});
let currentDrawerElementId = computed(() => {return useLowCodeStore().currentDrawerElementId});
let currentDrawerTitle = computed(() => {return useLowCodeStore().currentDrawerTitle});

let list = ref([]);
let itemFlag = ref(true);
let dialogVisible = ref(false);
let dialogSaveOrUpdateVisible = ref(false);
let componentRequestInfo = ref({});
let containerRules = ref({
    componentName: [{ required: true, message: '组件名称不能为空', trigger: 'blur' }],
    componentCnName: [{ required: true, message: '组件名称不能为空', trigger: 'blur' }]
});
let componentInfo = ref(null);
let saveLoading = ref(false);
let updateSaveLoading = ref(false);
let isShowGlobalDrawer = ref(false);
let globalComponentJson = ref({commonParam: [], leftPadding: "", rightPadding: "", topPadding: "", bottomPadding: "", isAddMixin: false, createdAction: [{isAsyncAction: false}]});

let router = useRouter();

// 创建标签
let route = useRoute();
createTag(route);

// 查询组件信息
componentInfoQueryById()

function deleteComponent(element) {
    let index = -1;
    // 遍历当前列表，删除元素ID对应的数据
    for (let i = 0; i < list.value.length; i++) {
        if (list.value[i].id === element.id) {
            index = i;
        }
    }
    if (index >= 0) {
        list.value.splice(index, 1);
    }
}

function changeComponentInfo(element) {
    useLowCodeStore().resetCurrentDrawer(element["drawerComponent"]);
    useLowCodeStore().resetCurrentDrawerTitle(element.title);
    useLowCodeStore().resetCurrentDrawerElementId(element.id);
    let copyJson = deepCopy(element.propJson)
    useLowCodeStore().resetLowCodeDrawerJsonInfo(copyJson);
    useLowCodeStore().resetIsShowDrawer(true);
    useLowCodeStore().resetLowCodeComponentList(list.value);
}

function globalComponentDrawer() {
    useLowCodeStore().resetLowCodeDrawerJsonInfo(deepCopy(globalComponentJson.value));
    isShowGlobalDrawer.value = true
}

function handleGlobalClose() {
    isShowGlobalDrawer.value = false;
}

function cancelGlobalClick() {
    isShowGlobalDrawer.value = false;
}

function confirmGlobalClick() {
    globalComponentJson.value = useLowCodeStore().lowCodeDrawerJsonInfo;
    // 重新加载组件
    itemFlag.value = false;
    nextTick(() => {
        itemFlag.value = true
    })
    isShowGlobalDrawer.value = false;
}

function handleClose() {
    ElMessageBox.confirm('是否确定保存修改')
        .then(() => {
            useLowCodeStore().resetIsShowDrawer(false);
        })
}

function cancelClick() {
    useLowCodeStore().resetIsShowDrawer(false);
}

function confirmClick() {
    // 将抽屉中修改的json设置到element元素中
    let componentList = useLowCodeStore().lowCodeComponentList;
    for (let i = 0; i < componentList.length; i++) {
        if (componentList[i].id === currentDrawerElementId.value) {
            componentList[i].propJson = useLowCodeStore().lowCodeDrawerJsonInfo;
            break;
        }
    }
    useLowCodeStore().resetLowCodeComponentList(componentList);
    // 重新加载组件
    itemFlag.value = false;
    nextTick(() => {
        itemFlag.value = true
    })
    useLowCodeStore().resetIsShowDrawer(false);
}

function clearAll() {
    ElMessageBox.confirm('是否确定清空所有组件', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        showCancelButton: true,
        dangerouslyUseHTMLString: true,
    })
        .then(() => {
            list.value = [];
            useLowCodeStore().resetLowCodeDrawerJsonInfo("");
        })
}

function replaceEditFlag(jsonObj) {
    // 匹配任意路径下的editFlag
    let editStr = "$..editFlag";
    jsonpath.apply(jsonObj, editStr, function (res) {
        return false;
    })
}

function getSlotContent(jsonObj, tempTemplateSlotInfo) {
    let slotRes = ""
    let slotStrPath = "$..slotList";
    let getRes = jsonpath.query(jsonObj, slotStrPath)
    if (getRes.length === 0) {
        return slotRes;
    }
    for (let i = 0; i < getRes.length; i++) {
        let res = getRes[i]
        for (let j = 0; j < res.length; j++) {
            tempTemplateSlotInfo.push(res[j])
            let templateInfo = `
                                    <template v-slot:${res[j].slotName}="slotProps">
                                        ${res[j].slotContent}
                                    </template>
                    `
            slotRes += templateInfo
        }
    }
    return slotRes;
}

let containerFormRef = ref<FormInstance>()
function saveComponent(formEl: FormInstance | undefined) {
    if (!formEl) return
    saveLoading.value = true
    formEl.validate((valid) => {
        if (valid) {
            // 待保存的组件template模板
            let componentParam = {
                componentName: componentRequestInfo.value.componentName,
                componentCnName: componentRequestInfo.value.componentCnName,
                componentType: "CUSTOM",
                componentTemplate: "",
                componentData: "",
                componentComputed: "",
                componentJson: ""
            }
            let infoJsonMix = {
                common: JSON.stringify(list.value),
                global: JSON.stringify(globalComponentJson.value)
            }
            componentParam.componentJson = JSON.stringify(infoJsonMix)
            // 遍历当前画布中的所有组件
            let tempTemplateSlotInfo = []
            for (let i = 0; i < list.value.length; i++) {
                let componentJsonInfo = list.value[i];
                let propJsonStr = JSON.stringify(componentJsonInfo.propJson);
                // 将 editFlag: true 替换为 false
                let jsonObj = JSON.parse(propJsonStr);
                // 如果为布局组件，则向下递归设置editFlag
                if (componentJsonInfo.component === "LayOutComponent" ||
                    componentJsonInfo.component === "GlobalFormComponent" ||
                    componentJsonInfo.component === "DialogComponent") {
                    replaceEditFlag(jsonObj)
                }
                jsonObj.editFlag = false;
                let slotContentInfo = getSlotContent(jsonObj, tempTemplateSlotInfo)
                let res = JSON.stringify(jsonObj).replaceAll("\"", '\'');
                let templateContent = `
                            <div style="">
                                <component is="${componentJsonInfo.component}" :propJson="${res}" :commonParam="commonParam">
                                    ${slotContentInfo}
                                </component>
                            </div>
                        `;
                componentParam.componentTemplate += templateContent;
            }
            let tempP = {
                variableName: "templateSlotInfo",
                variableValue: tempTemplateSlotInfo,
                variableType: "Array"}
            globalComponentJson.value.commonParam.push(tempP)
            let paramData = {
                commonParam: globalComponentJson.value.commonParam,
                isMixIn: globalComponentJson.value.isAddMixin
            }
            componentParam.componentData = JSON.stringify(paramData)
            let createdData = {
                createdData: globalComponentJson.value.createdAction
            }
            componentParam.componentCreated = JSON.stringify(createdData)
            // 添加全局div
            let globalStyle = "";
            if (globalComponentJson.value.leftPadding) {
                globalStyle += "padding-left: " + globalComponentJson.value.leftPadding + ";";
            }
            if (globalComponentJson.value.topPadding) {
                globalStyle += "padding-top: " + globalComponentJson.value.topPadding + ";";
            }
            if (globalComponentJson.value.bottomPadding) {
                globalStyle += "padding-bottom: " + globalComponentJson.value.bottomPadding + ";";
            }
            if (globalComponentJson.value.rightPadding) {
                globalStyle += "padding-right: " + globalComponentJson.value.rightPadding + ";";
            }
            globalStyle += "min-width: 900px;min-height: 900px";
            componentParam.componentTemplate = `<div style='${globalStyle}'>${componentParam.componentTemplate}</div>`
            // 添加组件
            componentInfoCreate(componentParam).then(res => {
                ElNotification({
                    title: 'Success',
                    message: res["message"],
                    type: 'success'
                });
                dialogVisible.value = false;
                router.push({name:'lowcodeBuilder',query: {id:res.data}, replace: true})
                saveLoading.value = false
            }).catch(res => {
                saveLoading.value = false
            })
        }
    })
}

function updateComponentBefore() {
    updateSaveLoading.value = true
    componentInfoQueryById()
    // 待保存的组件template模板
    let componentParam = {
        id: route.query.id,
        componentName: componentInfo.value.componentName,
        componentCnName: componentInfo.value.componentCnName,
        componentType: "CUSTOM",
        componentTemplate: "",
        componentData: "",
        componentComputed: "",
        componentJson: ""
    }
    let infoJsonMix = {
        common: JSON.stringify(list.value),
        global: JSON.stringify(globalComponentJson.value)
    }
    componentParam.componentJson = JSON.stringify(infoJsonMix)
    // 遍历当前画布中的所有组件
    let tempTemplateSlotInfo = []
    for (let i = 0; i < list.value.length; i++) {
        let componentJsonInfo = list.value[i];
        let propJsonStr = JSON.stringify(componentJsonInfo.propJson);
        // 将 editFlag: true 替换为 false
        let jsonObj = JSON.parse(propJsonStr);
        replaceEditFlag(jsonObj)
        let slotContentInfo = getSlotContent(jsonObj, tempTemplateSlotInfo)
        let res = JSON.stringify(jsonObj).replaceAll("\"", '\'');
        let templateContent = `
                            <div style="">
                                <component is="${componentJsonInfo.component}" :propJson="${res}" :commonParam="commonParam">
                                    ${slotContentInfo}
                                </component>
                            </div>
                        `;
        componentParam.componentTemplate += templateContent;
    }
    let tempP = {
        variableName: "templateSlotInfo",
        variableType: "Array",
        variableValue: tempTemplateSlotInfo
    }
    globalComponentJson.value.commonParam.push(tempP)
    let paramData = {
        commonParam: globalComponentJson.value.commonParam,
        isMixIn: globalComponentJson.value.isAddMixin
    }
    componentParam.componentData = JSON.stringify(paramData)
    let createdData = {
        createdData: globalComponentJson.value.createdAction
    }
    componentParam.componentCreated = JSON.stringify(createdData)
    // 添加全局div样式
    let globalStyle = "";
    if (globalComponentJson.value.leftPadding) {
        globalStyle += "padding-left: " + globalComponentJson.value.leftPadding + ";";
    }
    if (globalComponentJson.value.topPadding) {
        globalStyle += "padding-top: " + globalComponentJson.value.topPadding + ";";
    }
    if (globalComponentJson.value.bottomPadding) {
        globalStyle += "padding-bottom: " + globalComponentJson.value.bottomPadding + ";";
    }
    if (globalComponentJson.value.rightPadding) {
        globalStyle += "padding-right: " + globalComponentJson.value.rightPadding + ";";
    }
    globalStyle += "min-width: 900px;min-height: 900px";
    componentParam.componentTemplate = `<div style='${globalStyle}'>${componentParam.componentTemplate}</div>`
    componentInfoUpdate(componentParam).then(res => {
        ElNotification({
            title: 'Success',
            message: res["message"],
            type: 'success'
        });
        dialogSaveOrUpdateVisible.value = false;
        componentInfoQueryById()
        updateSaveLoading.value = false
    }).catch(res => {
        updateSaveLoading.value = false
    })
}

function saveComponentBefore() {
    dialogSaveOrUpdateVisible.value = false;
    dialogVisible.value = true;
}

function componentInfoQueryById() {
    let componentId = route.query.id
    if (!componentId) {
        componentInfo.value = null
        return
    }
    let param = {
        id: componentId,
        pageInfo: {
            pageIndex: 1,
            pageSize: 10
        }
    }
    // 查询组件详细信息
    componentInfoQuery(param).then(res => {
        if (res["code"] === '200') {
            let dataList = res.data["dataList"]
            if (dataList.length > 0) {
                let dataInfo = dataList[0]
                let jsonInfo = JSON.parse(dataInfo.componentJson)
                list.value = JSON.parse(jsonInfo.common)
                globalComponentJson.value = JSON.parse(jsonInfo.global)
                componentInfo.value = dataInfo
            }
        }
    })
}
</script>

<style scoped lang="less">
.lowCodeContainer {
    // 界面禁止选中
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+ */
    user-select: none; /* Standard syntax */
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    .leftContainer {
        width: 15%;
        height: 100%;
        overflow: auto;
    }
    .rightContainer {
        width: 85%;
        height: 100%;
        .topContainer {
            margin-left: 1%;
            margin-bottom: 0.5%;
            margin-top: 0.3%;
            width: 97%;
            height: 50px;
            //去除光标
            caret-color: transparent;
            box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            padding-left: 1%;
        }
        .draggableContainer {
            width: 98%;
            height: 85vh;
            margin-left: 1%;
            padding-top: 0.2%;
            transition: box-shadow 0.3s ease;
            box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5);
            //去除光标
            caret-color: transparent;
            overflow: auto;
            .draggableClass {
                width: 100%;
                height: 100%;
            }
            .itemClass {
                position: relative;
                transition: box-shadow 0.3s ease;
                margin-bottom: 0.3%;
                .closeClass {
                    display: none;
                }
            }
            .itemClass:hover {
                cursor: pointer;
                box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5);
                .closeClass {
                    position: absolute;
                    color: #e76565;
                    top: 2px;
                    right: 2px;
                    display: block;
                }
            }
        }
        .draggableContainer:hover {
            cursor: pointer;
        }
    }
}

/* 自定义整个滚动条 */
.leftContainer::-webkit-scrollbar {
    width: 5px; /* 设置滚动条的宽度 */
}

/* 自定义滚动条轨道 */
.leftContainer::-webkit-scrollbar-track {
    background: #f1f1f1; /* 设置轨道的背景颜色 */
}

/* 自定义滚动条的滑块（thumb） */
.leftContainer::-webkit-scrollbar-thumb {
    background: #b7b7b7; /* 设置滑块的背景颜色 */
    border-radius: 20px;
}

/* 当滑块悬停或活动时的样式 */
.leftContainer::-webkit-scrollbar-thumb:hover {
    background: #a9a9a9; /* 设置滑块在悬停状态下的背景颜色 */
}

/* 自定义整个滚动条 */
.draggableContainer::-webkit-scrollbar {
    width: 8px; /* 设置滚动条的宽度 */
}

/* 自定义滚动条轨道 */
.draggableContainer::-webkit-scrollbar-track {
    background: #f1f1f1; /* 设置轨道的背景颜色 */
}

/* 自定义滚动条的滑块（thumb） */
.draggableContainer::-webkit-scrollbar-thumb {
    background: #b7b7b7; /* 设置滑块的背景颜色 */
    border-radius: 20px;
}

/* 当滑块悬停或活动时的样式 */
.draggableContainer::-webkit-scrollbar-thumb:hover {
    background: #a9a9a9; /* 设置滑块在悬停状态下的背景颜色 */
}
</style>